#include "stdafx.h"
#include "ext/standard/info.h"
#include "Common.h"
#include <zend_constants.h>
#include <sstream>
#include <comutil.h>

/* constants */
#define AZURE_VERSION "1.1.4-dev"
#define AZURE_LOG_CRITICAL		1
#define AZURE_LOG_ERROR			2
#define AZURE_LOG_WARNING		3
#define AZURE_LOG_INFORMATION	4
#define AZURE_LOG_VERBOSE		5

#define REGISTER_AZURE_CONSTANT(__c) REGISTER_LONG_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT)

/* declaration of functions to be exported */
PHP_MINFO_FUNCTION(azure); 
ZEND_FUNCTION(azure_getconfig);
ZEND_FUNCTION(azure_log);
ZEND_FUNCTION(azure_getlocalresourcepath);
ZEND_FUNCTION(azure_getlocalresourcepathsize);
PHP_MINIT_FUNCTION(azure);

/* compiled function list so Zend knows what's in this module */
zend_function_entry AzureModule_functions[] = {
	ZEND_FE(azure_getconfig, NULL)
	ZEND_FE(azure_log, NULL)
	ZEND_FE(azure_getlocalresourcepath, NULL)
	ZEND_FE(azure_getlocalresourcepathsize, NULL)
    {NULL, NULL, NULL}
};

/* compiled module information */
zend_module_entry AzureModule_module_entry = {
    STANDARD_MODULE_HEADER,
    "azure",
    AzureModule_functions,
    PHP_MINIT(azure), NULL, NULL, NULL, PHP_MINFO(azure),
    AZURE_VERSION, STANDARD_MODULE_PROPERTIES
};

/* implement standard "stub" routine to introduce ourselves to Zend */
ZEND_GET_MODULE(AzureModule)

/* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(azure)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "Windows Azure Support", "enabled");
	php_info_print_table_row(2, "Version", AZURE_VERSION);
	php_info_print_table_row(2, "Url", "http://phpazurecontrib.codeplex.com");
	php_info_print_table_end();
}
/* }}} */

/* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(azure)
{
	REGISTER_AZURE_CONSTANT(AZURE_LOG_CRITICAL);
	REGISTER_AZURE_CONSTANT(AZURE_LOG_ERROR);
	REGISTER_AZURE_CONSTANT(AZURE_LOG_WARNING);
	REGISTER_AZURE_CONSTANT(AZURE_LOG_INFORMATION);
	REGISTER_AZURE_CONSTANT(AZURE_LOG_VERBOSE);
	
	return SUCCESS;
}
/* }}} */
 
/* {{{ proto string azure_getconfig(string key)
   Get Windows Azure configuration key */
PHP_FUNCTION(azure_getconfig)
{
    char* key;
	int key_len;
	
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
		//RETURN_STRING("Parameter error", 1);
		RETURN_BOOL(false);
	}

	try {
		InitializeRoleEnvironment();
	} catch ( char * ex ) {
		//RETURN_STRING(ex, 1);
		RETURN_BOOL(false);
	}

	try {
		std::string result = GetConfigurationSetting( (LPCSTR)key );
		char* cstr = (char*)emalloc(result.size()+1);
		strcpy((char*) cstr, result.c_str());
		
		RETURN_STRING(cstr, 0); 
	} catch ( char * ex ) {
		//RETURN_STRING(ex, 1);
		RETURN_BOOL(false);
	}
}
/* }}} */

/* {{{ proto bool azure_log(int log, string message)
   Append log entry */
PHP_FUNCTION(azure_log)
{
	long log = 4;

    char* message;
	int message_len;
	
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &log, &message, &message_len) == FAILURE) {
		//RETURN_STRING("Parameter error", 1);
		RETURN_BOOL(false);
	}

	try {
		InitializeLogging();
	} catch ( char * ex ) {
		//RETURN_STRING(ex, 1);
		RETURN_BOOL(false);
	}

	// Convert char * to wchar *, needed for Azure Logging
	int len = lstrlenA(message);
	BSTR wide_message = SysAllocStringLen(NULL, len);
	::MultiByteToWideChar(CP_ACP, 0, message, len, wide_message, len);	

	try {
		switch(log) {
			case AZURE_LOG_CRITICAL:	LogCritical( (LPCWSTR) wide_message);		break;
			case AZURE_LOG_ERROR:		LogError( (LPCWSTR) wide_message);			break;
			case AZURE_LOG_WARNING:		LogWarning( (LPCWSTR) wide_message);		break;
			case AZURE_LOG_INFORMATION: LogInformation( (LPCWSTR) wide_message);	break;
			case AZURE_LOG_VERBOSE:		LogVerbose( (LPCWSTR) wide_message);		break;
			default:					LogVerbose( (LPCWSTR) wide_message);		break;
		}		
	} catch ( char * ex ) {
		//RETURN_STRING(ex, 1);
		
		// free the wide string message
		::SysFreeString(wide_message);

		RETURN_BOOL(false);
	}

	// free the wide string message
	::SysFreeString(wide_message);

	RETURN_BOOL(true);
}
/* }}} */

/* {{{ proto string azure_getlocalresourcepath(string name)
   Get Windows Azure local resource path */
PHP_FUNCTION(azure_getlocalresourcepath)
{
    char* name;
	int name_len;
	
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
		//RETURN_STRING("Parameter error", 1);
		RETURN_BOOL(false);
	}

	try {
		InitializeRoleEnvironment();
	} catch ( char * ex ) {
		//RETURN_STRING(ex, 1);
		RETURN_BOOL(false);
	}

	try {
		std::string result = GetLocalResourceRootPath( (LPCSTR)name );
		char* cstr = (char*)emalloc(result.size()+1);
		strcpy((char*) cstr, result.c_str());
		
		RETURN_STRING(cstr, 0); 
	} catch ( char * ex ) {
		//RETURN_STRING(ex, 1);
		RETURN_BOOL(false);
	}
}
/* }}} */

/* {{{ proto int azure_getlocalresourcepathsize(string name)
   Get Windows Azure local resource path size in MB */
PHP_FUNCTION(azure_getlocalresourcepathsize)
{
    char* name;
	int name_len;
	
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
		//RETURN_STRING("Parameter error", 1);
		RETURN_BOOL(false);
	}

	try {
		InitializeRoleEnvironment();
	} catch ( char * ex ) {
		//RETURN_STRING(ex, 1);
		RETURN_BOOL(false);
	}

	try {
		long result = GetLocalResourceRootPathSize( (LPCSTR)name );
		RETURN_LONG(result); 
	} catch ( char * ex ) {
		//RETURN_STRING(ex, 1);
		RETURN_BOOL(false);
	}
}
/* }}} */